<?php if(!defined('BASEPATH')) exit('No direct access to this file allowed');

/******************************************************************************\
 *  Router
 *
 *  TODO:
 *  handle query string (e.g. m=1, f=2, c=3). Default behavior for query
 *  string is m = module, c = controller, f = function
 *
 *  Change Log
 *  0.1     -   Initial version of Router
 *
 *  Standard Tags:
 *  @author     Ruben Tan
 *  @copyright  Copyright (c) 2008 Rendervault
 *
 *  Developer Tags:
 *  @package    system
 *  @subpackage core
\******************************************************************************/
class Router
{
    protected $_hooks = array();    
    protected $_route_table = NULL;

    public function __construct( $IB )
    { 
        $this->IB = $IB;
    }
    
    /**--------------------------------------------------------------------------------------
     *  Executes the router. First it'll get the URI string, clean it, sanitize it, and then
     *  looks up the routing table to find the proper resource requested. If a routing table
     *  is not provided, it will fall back to its default behavior:
     *
     *  http://host/index.php?m=modulename&f=functionname (if no rewrite rules is available)
     *  http://host/module/functionname (if rewrite rules exist)
     *
     *  @author     Ruben Tan
     *
     *  @access     protected
     *  @param      void
     *  @return     string      a query string
     */
    public function run()
    {       
        if( !isset($this->IB) ) throw new Exception( 'Unable to reference IgnitionBase core' );
    
        // Get the URI string for routing purposes
        $uri_string = $this->_get_uri_string( );
        $uri = $this->_uri_to_array( $uri_string );
    
        // Check if has routing rules
        if( isset( $this->_route_table ) )
        {
            // Parse routing variables
            // NOTE: To Be Implemented
            
        }
        else
        {
            $controller = null;
            $function = '';
            $controller_name = '';
            
            // If no URI is passed in, automatically assume that the main
            // controller would be 'Main' in the module 'main'
            if( count( $uri ) == 0 )
            {
                $controller_name = 'main';
                $controller = $this->IB->load( IgnitionBase::MODULE, 'main' . NS . 'controllers' . NS . 'main' );
            }
            else
            {
                // Fall back to default behavior
                $module_name = $uri[0];
                
                // If no controller defined, automatically assume it would be
                // the same as the module's name
                if( count( $uri ) <= 1 )
                {
                    $controller_name = $module_name;
                }
                else
                {
                    $controller_name = $uri[1];
                }
                
                // Load the controller
                $controller = $this->IB->load( IgnitionBase::MODULE, $module_name . NS . 'controllers' . NS . $controller_name );
            }    
            
            // If no function defined, automatically call the function 'index'
            if( count( $uri ) <= 2 )
            {
                $function = 'index';
            }
            else
            {
                $function = $uri[2];
            }
            
            // Check if the function exists or not
            if( !in_array( $function, get_class_methods( $controller ) ) )
            {
                throw new Exception( 'Unable to call the function: ' . $function . '() in controller: ' . $controller_name );
            }
            
            // Call the function and rejoice!
            call_user_func( array($controller, $function) );
        }
    }
    
    public function set_hook( $callback )
    {
        if( is_array( $callback ) )
        {
            
        }
        elseif ( is_function( $callback ) )
        {
            
        }
    }
    
    public function hook( $hook )
    {
        $this->_hooks[$hook] = null;
    }
    
    /**--------------------------------------------------------------------------------------
     *  Extracts the URI string from the request. This function is lifted off verbatim from
     *  CodeIgniter's library (http://www.codeigniter.com), since it works so well. 
     *
     *  @author     CodeIgniter (http://www.codeigniter.com)
     *
     *  @access     protected
     *  @param      void
     *  @return     string      a query string
     */
    protected function _get_uri_string( )
    {
        // If the URL has a question mark then it's simplest to just
        // build the URI string from the zero index of the $_GET array.
        // This avoids having to deal with $_SERVER variables, which
        // can be unreliable in some environments
        if ( is_array( $_GET ) && count( $_GET ) == 1 && trim( key($_GET), '/' ) != '' )
        {
            return key( $_GET );
        }
    
        // Is there a PATH_INFO variable?
        // Note: some servers seem to have trouble with getenv() so we'll test it two ways		
        $path = ( isset( $_SERVER['PATH_INFO'] ) ) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');			
        if ( trim( $path, '/' ) != '' && $path != "/".SELF )
        {
            return $path;
        }
                
        // No PATH_INFO?... What about QUERY_STRING?
        $path =  ( isset( $_SERVER['QUERY_STRING'] ) ) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');	
        if ( trim( $path, '/' ) != '' )
        {
            return $path;
        }
        
        // No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
        $path = ( isset( $_SERVER['ORIG_PATH_INFO'] ) ) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');	
        if ( trim( $path, '/' ) != '' && $path != "/" . SELF )
        {
            // Remove path and script information so we have good URI data
            return str_replace( $_SERVER['SCRIPT_NAME'], '', $path );
        }

        // We've exhausted all our options...
        return '';
    }
    
    /**--------------------------------------------------------------------------------------
     *  Parses the URI and returns an array containing parameters of it
     *
     *  @author     CodeIgniter (http://www.codeigniter.com)
     *
     *  @access     protected
     *  @param      string      the URI string
     *  @return     mixed       an array containing the parameters or FALSE if nothing is found
     */
    protected function _uri_to_array( $uri_string )
    {
        $result = explode( '/', $uri_string );
        
        // Because the first element of the URI array might be an empty string, shift it if needed
        if( $result !== FALSE && $result[0] === '' )
        {
            array_shift($result);
        }
        
        return $result;
    }
    
    protected function _parse_uri_string( )
    {
        
    }
}